let User = syzoj.model('user');
let PendingUser = syzoj.model('pending_user');
let Article = syzoj.model('article');
let Contest = syzoj.model('contest');
let Problem = syzoj.model('problem');
let Divine = syzoj.lib('divine');
let TimeAgo = require('javascript-time-ago');
let zh = require('../libs/timeago');
TimeAgo.locale(zh);
const timeAgo = new TimeAgo('zh-CN');

app.get('/', async (req, res) => {
  try {
    let ranklist = await User.queryRange([1, syzoj.config.page.ranklist_index], { is_show: true }, {
      [syzoj.config.sorting.ranklist.field]: syzoj.config.sorting.ranklist.order
    });
    await ranklist.forEachAsync(async x => x.renderInformation());

    let noticest = (await Article.find({
      where: { is_notice: true }, 
      order: { public_time: 'DESC' }
    }));
    let notices = [];
    for (let i = 0; i < noticest.length; i++) {
      notices.push ({
        title: noticest[i].title,
        url: syzoj.utils.makeUrl(['article', noticest[i].id]),
        date: syzoj.utils.formatDate(noticest[i].public_time, 'L'),
        user: await User.findById(noticest[i].user_id)
      });
    }

    let fortune = null;
    if (res.locals.user) {
      fortune = Divine(res.locals.user.username, res.locals.user.sex);
    }

    let contests = await Contest.queryRange([1, 5], { is_public: true }, {
      start_time: 'DESC'
    });

    let problems = (await Problem.queryRange([1, 5], { is_public: true }, {
      publicize_time: 'DESC'
    })).map(problem => ({
      id: problem.id,
      title: problem.title,
      time: timeAgo.format(new Date(problem.publicize_time)),
    }));

    let pending_user = await PendingUser.find ();

    let getCompetition = function (date) {
      let getCspDay = function (year) { // the penultimate Saturday in October
        for (let i = 18; i <= 24; ++i) {
          let d = new Date (year, 9, i); // !!!!!!!!!! months in Date are 0~11
          if (d.getDay () == 6) return d;
        }
      }
      let getNoipDay = function (year) { // the penultimate Saturday in November
        for (let i = 17; i <= 23; ++i) {
          let d = new Date (year, 10, i); // !!!!!!!!!! months in Date are 0~11
          if (d.getDay () == 6) return d;
        }
      }
      let getTime = function (day) {return (day - date) / (1000 * 60 * 60 * 24);}
      let getColor = function (day) {
        if (day <= 10) return "#e74c3c";
        if (day <= 20) return "#e67e22";
        if (day <= 30) return "#f1c40f";
        return "#2dce89";
      }
      let getArc = function (day) {return day / 365 * 409;}
      let year = date.getFullYear (),
          ThisCsp = getTime (getCspDay (year)),
          ThisNoip = getTime (getNoipDay (year)),
          NextCsp = getTime (getCspDay (year + 1)),
          day, name;
      if (ThisCsp > -1) day = Math.max (ThisCsp, 0), name = "CSP-J/S " + year;
      else if (ThisNoip > -1) day = Math.max (ThisNoip, 0), name = "NOIp " + year;
      else day = NextCsp, name = "CSP-J/S " + (year + 1);
      return {
        name: name,
        day: Math.ceil (day),
        color: getColor (Math.ceil (day)),
        arc: getArc (day)
      };
    };

    res.render('index', {
      ranklist: ranklist,
      notices: notices,
      fortune: fortune,
      contests: contests,
      problems: problems,
      links: syzoj.config.links,
      is_logined: !!res.locals.user,
      allowedManage: res.locals.user && await res.locals.user.hasPrivilege('manage_user'),
      pending_user: pending_user,
      competition: getCompetition (new Date ())
    });
  } catch (e) {
    syzoj.log(e);
    res.render('error', {
      err: e
    });
  }
});

app.get('/help', async (req, res) => {
  try {
    if (!res.locals.user) throw new ErrorMessage('请登录后继续。', { '登录': syzoj.utils.makeUrl(['login'], { 'url': req.originalUrl }) });
    res.render('help');
  } catch (e) {
    syzoj.log(e);
    res.render('error', {
      err: e
    });
  }
});
